package net.java.mediasystems.web.bean;

import java.util.ArrayList;
import java.util.List;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import org.primefaces.context.RequestContext;

import net.java.mediasystems.database.core.model.Metadata;
import net.java.mediasystems.database.core.model.MetadataValue;
import net.java.mediasystems.database.core.service.MetadataService;
import net.java.mediasystems.web.WebUtil;

/**
 * AbstractEmbededMetadataValueInputBean.
 */
public abstract class AbstractEmbededMetadataValueInputBean {
	
	List<MetadataSelectionElement> metadataSelectionModel;
	private String metadataDefName;
	
	private transient MetadataService metadataService;
	
	abstract String getMetadataCategory();
	
	/**
	 * Save the Metadata, which can afterwards be bound to Object, that can hold Metadata (a StorageContainer or a MediaItem).
	 */
	public void saveMetadataDefinition() {
		System.out.println("Calling the method saveMetadataDefinition()");
		
		Metadata metadata = new Metadata();
		metadata.setName(this.metadataDefName);
		metadata.setCategory(getMetadataCategory());
		
		this.metadataService.addMetadata(metadata);
		
		MetadataSelectionElement metadataSelectionElement = new MetadataSelectionElement(metadata);
		this.metadataSelectionModel.add(metadataSelectionElement);
		
		this.metadataDefName = null;
		
		// Use RequestContext to execute Javascript to close the modal Dialog
		RequestContext.getCurrentInstance().execute("mdefInputDialog.hide();");
	}
	
	/**
	 * Validation-Method to check, if the Name already exists for the defined Category.
	 * 
	 * @param facesContext FacesContext
	 * @param uiComponent UIComponent
	 * @param value Object
	 */
	public void checkNameForCategory(FacesContext facesContext, UIComponent uiComponent, Object value) {
		String name = (String) value; 
		System.out.println("Checking the Name " + name + ", if it exists already in the DB!!!");
		if (this.metadataService.getMetadataDefinitionByCategoryAndName(getMetadataCategory(), name) != null) {
			throw new ValidatorException(WebUtil.createErrorMessageLocalized("inc_addmetadatadefinitionmodaldialog_error_namealreadyexists"));
		}
	}
	
	List<MetadataValue> grabSelectedMetadata() {
		List<MetadataValue> selectedMetadataValues = new ArrayList<MetadataValue>();
		for (MetadataSelectionElement curSelectionElement : this.metadataSelectionModel) {
			if (curSelectionElement.isSelected() && !curSelectionElement.getValue().isEmpty()) {
				MetadataValue metadataValue = new MetadataValue();
				metadataValue.setMetadata(curSelectionElement.getMetadata());
				metadataValue.setValue(curSelectionElement.getValue());
				selectedMetadataValues.add(metadataValue);
			}
		}
		return selectedMetadataValues;
	}
	
	/**
	 * Innerclass for the Tablemodel-Element.
	 * 
	 */
	public class MetadataSelectionElement {
		
		public MetadataSelectionElement(Metadata metadata) {
			this.metadata = metadata;
		}
		
		private boolean selected;
		private Metadata metadata;
		private String value;
		
		public boolean isSelected() {
			return selected;
		}
		public void setSelected(boolean selected) {
			this.selected = selected;
		}
		public Metadata getMetadata() {
			return metadata;
		}
		public void setMetadata(Metadata metadata) {
			this.metadata = metadata;
		}
		public String getValue() {
			return value;
		}
		public void setValue(String value) {
			this.value = value;
		}
	}
	
	public List<MetadataSelectionElement> getMetadataSelectionModel() {
		if (this.metadataSelectionModel == null) {
			this.metadataSelectionModel = createMetadataSelectionModel();
		}
		return metadataSelectionModel;
	}
	
	private List<MetadataSelectionElement> createMetadataSelectionModel() {
		ArrayList<MetadataSelectionElement> metadataSelection = new ArrayList<MetadataSelectionElement>();
		List<Metadata> foundMetadataDefs = this.metadataService.getAllMetadataDefinitionByCategory(getMetadataCategory());
		
		for (Metadata curMetadata : foundMetadataDefs) {
			MetadataSelectionElement selectionElement = new MetadataSelectionElement(curMetadata);
			metadataSelection.add(selectionElement);
		}
		
		return metadataSelection;
	}

	public void setMetadataSelectionModel(
			List<MetadataSelectionElement> metadataSelectionModel) {
		this.metadataSelectionModel = metadataSelectionModel;
	}

	public void setMetadataService(MetadataService metadataService) {
		this.metadataService = metadataService;
	}
	
	public String getMetadataDefName() {
		return metadataDefName;
	}

	public void setMetadataDefName(String metadataDefName) {
		this.metadataDefName = metadataDefName;
	}
}
